package com.tools.web.interceptor.quota;

import com.tools.common.object.Note;
import com.tools.common.thread.Timeunit;
import com.tools.db.cache.expiring.ExpiringMap;

/**
 * 使用过期 Map 集合 ExpiringMap 实现配额限制拦截器
 * 【注意】：业务成功后必须通过该拦截器实例的 incrSuccessfulCount 方法进行次数自增。
 * */
@Note("使用过期 Map 集合 ExpiringMap 实现配额限制拦截器." +
        "【注意】：业务成功后必须通过该拦截器实例的 incrSuccessfulCount 方法进行次数自增。")
public final class ExpiringMapQuotaInterceptor extends QuotaInterceptor {

    @Note("过期 Map 集合本地缓存实例")
    private final ExpiringMap<String, Object> cache;

    public ExpiringMapQuotaInterceptor(ExpiringMap<String, Object> cache, QuotaSource source) {
        super(source, cache != null, "本地缓存实例不能为 null");
        this.cache = cache;
    }


    @Override
    public void incrSuccessfulCount(String uniqueID, String action, long createExpiration, Timeunit createTimeunit) {
        String key = super.protected_getCachePrefix() + action + ':' + uniqueID;
        synchronized (key) {
            Integer successFulCount = (Integer) this.cache.get(key);
            if(successFulCount == null) {
                this.cache.put(key, 1, createExpiration, createTimeunit);
                return;
            }
            long ttl = this.cache.getExpectedExpiration(key);
            if(ttl < 1) {
                this.cache.put(key, 1, createExpiration, createTimeunit);
                return;
            }
            this.cache.put(key, successFulCount + 1, ttl, Timeunit.MILL);
        }
    }

    @Override
    protected Integer protected_getSuccessfulCount(String key) {
        return (Integer) this.cache.get(key);
    }

    @Override
    protected long protected_getRemainder(String key) {
        return this.cache.getExpectedExpiration(key);
    }
}
